﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using Trackr.Core.Entities;
using Trackr.GUI.Extensions;

namespace Trackr.GUI.ViewModels
{
    public class MainWindowViewModel
    {
        private readonly int _maxWeekNr;
        public Week CurrentWeek { get; set; }
        private readonly StopWatch _stopWatch;
        public Model.TimeItem CurrentModel.TimeItem { get; set; }

        public MainWindowViewModel()
        {
            CurrentModel.TimeItem = GetLatestModel.TimeItem();// Core.Trackr.Instance.GetLatestModel.TimeItem();
            if (CurrentModel.TimeItem != null)
                _maxWeekNr = CurrentModel.TimeItem.StartDate.GetWeek();
            SetCurrentWeek();

            _stopWatch = new StopWatch();
            _stopWatch.Start();
        }

        private Model.TimeItem GetLatestModel.TimeItem()
        {
            var lastDaty = CurrentWeek.Days.OrderBy(day => day.TimeEntries.OrderBy(entry => entry.Id)).First();
            return lastDaty.TimeEntries.OrderBy(entry => entry.Id).First();
        }

        public string PlaceholderText
        {
            get { return CurrentModel.TimeItem != null ? CurrentModel.TimeItem.Task : "What are you doing?"; }
            set { }
        }

        public string CurrentWeekNrText
        {
            get { return string.Format("week {0}", CurrentWeek.Number); }
        }

        public ObservableCollection<Day> DaysOfCurrentWeek
        {
            get
            {
                DateTime startDate = CurrentWeek.Number.GetWeekStartDate(CurrentWeek.Year);
                IEnumerable<Model.TimeItem> TimeItems = Core.Trackr.Instance.GetModel.TimeItems(startDate, startDate.AddDays(6));

                //get the days. group them by day date
                var days = Model.TimeItems.GroupBy(t => t.StartDate.Date)
                             .OrderByDescending(ti => ti.Key)
                             .ToDictionary(i => i.Key, i => i.ToList());
                var weekDays = new ObservableCollection<Day>();

                foreach (DateTime dayDate in days.Keys)
                {
                    var dayTimeItmes = new ObservableCollection<Model.TimeItem>(days[dayDate].OrderByDescending(ti => ti.StartDate));
                    weekDays.Add(new Day(dayDate, dayTimeItmes));
                }
                return weekDays;
            }
        }

        public event EventHandler TaskSubmitted;

        private void SetCurrentWeek()
        {
            CurrentWeek = new Week {Number = DateTime.Now.GetWeek(), Year = DateTime.Now.Year};
            CurrentWeek.Days = DaysOfCurrentWeek;
        }


        /// <summary>
        ///     Will stop/end the current time item
        ///     <para>Will add the duration of the current stopwatch to the current time item</para>
        /// </summary>
        public void StopCurrent()
        {
            if (CurrentModel.TimeItem == null)
                return;
            _stopWatch.Stop();
            CurrentModel.TimeItem.AddDuration(_stopWatch.Duration);
            Core.Trackr.Instance.Update(CurrentModel.TimeItem.Id, CurrentModel.TimeItem);
            _stopWatch.Clear();
        }

        #region commands

        private ICommand _leftKeyDownCommand;
        private ICommand _rightKeyDownCommand;
        private ICommand _showNextWeek;
        private ICommand _showPreviousWeek;
        private ICommand _submitTaskCommand;

        public ICommand SubmitTaskCommand
        {
            get
            {
                if (_submitTaskCommand != null)
                    return _submitTaskCommand;

                return _submitTaskCommand = new RelayCommand((obj) =>
                    {
                        var task = obj as string;
                        if (String.IsNullOrWhiteSpace(task))
                            return;

                        if (CurrentModel.TimeItem != null)
                        {
                            if (CurrentModel.TimeItem.Task == task)
                            {
                                if (TaskSubmitted != null)
                                    TaskSubmitted(CurrentModel.TimeItem, EventArgs.Empty);
                            }

                            _stopWatch.Stop();
                            CurrentModel.TimeItem.AddDuration(_stopWatch.Duration);
                            Core.Trackr.Instance.Update(CurrentModel.TimeItem.Id, CurrentModel.TimeItem);
                        }
                        Core.Trackr.Instance.AddNew(task);
                        CurrentModel.TimeItem = Core.Trackr.Instance.GetLatestModel.TimeItem();
                        _stopWatch.Start();
                        if (TaskSubmitted != null)
                            TaskSubmitted(CurrentModel.TimeItem, EventArgs.Empty);
                        //CurrentWeekView = GetDaysOfWeek(_currentWeek, _currentYear);
                        //System.Windows.MessageBox.Show(txt);
                    });
            }
        }

        public ICommand ShowPreviousWeek
        {
            get
            {
                if (_showPreviousWeek != null)
                    return _showPreviousWeek;

                return _showPreviousWeek = new RelayCommand((obj) => SetPreviousWeek());
            }
        }

        public ICommand ShowNextWeek
        {
            get
            {
                if (_showNextWeek != null)
                    return _showNextWeek;

                return _showNextWeek = new RelayCommand((obj) => SetNextWeek());
            }
        }

        public ICommand LeftKeyDownCommand
        {
            get
            {
                if (_leftKeyDownCommand != null)
                    return _leftKeyDownCommand;

                return _leftKeyDownCommand = new RelayCommand((obj) => SetPreviousWeek());
            }
        }

        public ICommand RightKeyDownCommand
        {
            get
            {
                if (_rightKeyDownCommand != null)
                    return _rightKeyDownCommand;

                return _rightKeyDownCommand = new RelayCommand((obj) => SetNextWeek());
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void SetPreviousWeek()
        {
            int currentWeek = CurrentWeek.Number;
            if (currentWeek == 1)
            {
                CurrentWeek.Number = 52;
                CurrentWeek.Year--;
            }
            else
            {
                CurrentWeek.Number--;
            }
            //CurrentWeekNr = CurrentWeekNr == 1 ? 52 : CurrentWeekNr -= 1;
            //CurrentWeekView = GetDaysOfWeek(_currentWeek, _currentYear);
        }

        private void SetNextWeek()
        {
            if (CurrentWeek.Number == _maxWeekNr)
                return;
            int currentWeek = CurrentWeek.Number;
            if (currentWeek == 52)
            {
                CurrentWeek.Number = 1;
                CurrentWeek.Year++;
            }
            else
            {
                CurrentWeek.Number++;
            }
            //CurrentWeekView = GetDaysOfWeek(CurrentWeekNr, _currentYear);
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion commands
    }
}